package com.lzyyj.gmis.base.dao;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.lzyyj.common.Page;

public class JpaBaseDAOImpl<T, PK extends Serializable> implements IBaseDao<T, PK> {

	/** Logger available to subclasses */
	protected final Log logger = LogFactory.getLog(getClass());

	/**
	 * JPQL 中使用的模型名称
	 */
	private String modelName = "model";

	/**
	 * 有效记录表达式
	 */
	private String validExpr = null;

	// property constants

	public String getValidExpr() {
		return validExpr;
	}

	public void setValidExpr(String validExpr) {
		this.validExpr = validExpr;
	}

	protected Class<T> entityClass;// DAO所管理的Entity类型.

	public Class<T> getEntityClass() {
		return entityClass;
	}

	public void setEntityClass(Class<T> entityClass) {
		this.entityClass = entityClass;
	}

	@PersistenceContext
	private EntityManager entityManager;

	public EntityManager getEntityManager() {
		return this.entityManager;
	}

	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}
	/**
	 * 无参构造方法，从继承关系中找到实际的实体类型，子类之一必须明确指示所使用的实体类型
	 */
	protected JpaBaseDAOImpl() {
		// 类型参数映射表
		Map<String, Object> typeParameters = new HashMap<String, Object>();
		// 获取当前实例类型
		Class clazz = getClass();
		Class superClass = clazz.getSuperclass();
		
		if (clazz != JpaBaseDAOImpl.class){
			while (clazz != null) {
				superClass = clazz.getSuperclass();
				Type genType = clazz.getGenericSuperclass();
				Type[] superTypes = superClass.getTypeParameters();
				if (genType instanceof ParameterizedType) {
					Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
					for (int i = 0; i < params.length; i++) {
						Type type = superTypes[i];
						Type sTemp = params[i];
						if (sTemp instanceof Class){
							typeParameters.put(type.toString(), (Class) sTemp);
							
						}else{
							if (typeParameters.containsKey(sTemp.toString())){
								typeParameters.put(type.toString(), typeParameters.get(sTemp.toString()));
							}
						}
					}

				} else {
				}

				clazz = superClass;

				if (superClass == JpaBaseDAOImpl.class){
					this.entityClass = (Class)typeParameters.get("T");
					break;
				}
			}
		}

	}

	/**
	 * 带参构造方法，为spring提供构实体类型注入方法
	 */
	public JpaBaseDAOImpl(Class<T> entityClass) {
		this.entityClass = entityClass;
	}

	/**
	 * 带参构造方法，为spring提供构实体类型注入方法，以及实体的有效性表达式
	 */
	public JpaBaseDAOImpl(Class<T> entityClass, String vildExpr) {
		this.entityClass = entityClass;
		this.validExpr = vildExpr;
	}

	public void delete(Object entity) {
		if (entity == null) {
			return;// //////
		} else {
			entityManager.remove(entity);
		}
	}

	public T save(T entity) {
		logger.info("正在保存 " + entityClass.getSimpleName() + " 实例");
		try {
			entityManager.persist(entity);
			logger.info("保存顺利完成!");
		} catch (RuntimeException re) {
			logger.error("保存失败", re);
			throw re;
		}
		
		return entity;
	}

	public void deleteById(PK id) {
		if (id != null) {
			T entity = this.getById(id);
			this.delete(entity);
		} else {
			return;// //////
		}
	}

	public void deleteByIds(PK[] ids) {
		for(PK id:ids){
			deleteById(id);
		}
	}

	public T update(T entity) {
		logger.info("updating " + entityClass.getSimpleName() + " instance");
		try {
			T result = entityManager.merge(entity);
			logger.info("update successful");
		} catch (RuntimeException re) {
			logger.error("update failed", re);
			throw re;
		}
		return entity;
	}

	public T saveOrUpdate(T entity) {
		return update(entity);
	}

	public void executeUpdate(String jpql, Object... values) {
		// TODO Auto-generated method stub
		
	}

	public T getNew() {
		// TODO Auto-generated method stub
		return null;
	}

	public T get(T entity) {
		// TODO Auto-generated method stub
		return null;
	}

	public T getById(PK id) {
		// TODO Auto-generated method stub
		return null;
	}

	public T load(PK id) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	public long getAllCount() {
		// TODO Auto-generated method stub
		return 0;
	}

	public long getCount(Map<String, Object> condition) {
		// TODO Auto-generated method stub
		return 0;
	}

	public boolean isUnique(T entity, String uniquePropertyNames) {
		// TODO Auto-generated method stub
		return false;
	}

	public T findUniqueBy(String propertyName, Object value) {
		// TODO Auto-generated method stub
		return null;
	}

	public T findUniqueBy(String propertyList, Object... values) {
		// TODO Auto-generated method stub
		return null;
	}

	public List<T> findAll() {
		// TODO Auto-generated method stub
		return null;
	}

	public List<T> findAll(String orderBy, long... firstAndMaxResults) {
		// TODO Auto-generated method stub
		return null;
	}

	public List<T> findAll(String fieldList, String orderFields,
			long... rowStartIdxAndCount) {
		// TODO Auto-generated method stub
		return null;
	}

	public List<T> findByExample(T instance, long... firstAndMaxResults) {
		// TODO Auto-generated method stub
		return null;
	}

	public List<T> findByExample(T entity, String propertyList, String orderBy,
			long... firstAndMaxResults) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	public List<T> findByProperty(String propertyName, Object value,
			String orderBy) {
		// TODO Auto-generated method stub
		return null;
	}

	public List<T> findByProperty(String propertyName, Object value,
			String orderBy, long... firstAndMaxResults) {
		// TODO Auto-generated method stub
		return null;
	}

	public Page<T> findByProperty(Page<T> page, String propertyName,
			Object value) {
		// TODO Auto-generated method stub
		return null;
	}

	public List<T> find(String hql, Object... values) {
		// TODO Auto-generated method stub
		return null;
	}

	public Page<T> find(Page<T> page) {
		// TODO Auto-generated method stub
		return null;
	}

	public List<T> findBy(String condition, long startIndex, long maxCount,
			String orderBy) {
		// TODO Auto-generated method stub
		return null;
	}

	public String getPKName() {
		// TODO Auto-generated method stub
		return null;
	}

	public void flush() {
		// TODO Auto-generated method stub
		
	}

	public void clear() {
		// TODO Auto-generated method stub
		
	}

	public long getCount(Page<T> page) {
		// TODO Auto-generated method stub
		return 0;
	}

	public long getCountByProperty(String propertyName, Object value,
			String orderBy) {
		// TODO Auto-generated method stub
		return 0;
	}

	public void merge(T entity) {
		// TODO Auto-generated method stub
		
	}

	public PK getPK(T entity) throws NoSuchMethodException,
			IllegalAccessException, InvocationTargetException {
		// TODO Auto-generated method stub
		return null;
	}

	public Query createQuery(String hql, Object... values) {
		// TODO Auto-generated method stub
		return null;
	}

	public void callProc(String procName, Object... values) throws SQLException {
		// TODO Auto-generated method stub
		
	}

	public String getPropertyList() {
		// TODO Auto-generated method stub
		return null;
	}

	public String[] getProperties() {
		// TODO Auto-generated method stub
		return null;
	}

	public boolean isEntity(Class clazz) {
		// TODO Auto-generated method stub
		return false;
	}

	public Object getByClass(Object value) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public long getCount(String condition) {
		// TODO 自动生成的方法存根
		return 0;
	}

	@Override
	public List<Map<String, Object>> getEntityNameList() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String[] getProperties(Class<?> entityClass) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public <E> List<E> findByProperty(Class<E> entityClass,
			String propertyName, Object value, String orderBy,
			long[] firstAndMaxResults) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public <T1, PK1 extends Serializable> IBaseDao<T1, PK1> getBaseDao(
			Class<T1> clazz1) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public long getIndex(T focus, Page<T> page) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public T save(T entity, String propertyList) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public T update(T entity, String propertyList) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public T get(T entity, String propertyList) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public T getById(PK id, String propertyList) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<T> findByExample(T entity, String propertyList, String orderBy, String propertyList2, long... firstAndMaxResults) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<T> findByProperty(String propertyName, Object value, String orderBy, String propertyList) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<T> findByProperty(String propertyName, Object value, String orderBy, String propertyList, long... firstAndMaxResults) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public <E> List<E> findByProperty(Class<E> entityClass, String propertyName, Object value, String orderBy, String propertyList, long... firstAndMaxResults) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public <E> Map<String, List<? extends Object>> getRefListMap(Class<E> objectClass, String aliasNames, E entityPo) throws ClassNotFoundException, Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getPkNameByEntityClass(Class<?> entityClass) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean isPersistentProperty(String propertyName) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public <E> boolean isPersistentProperty(Class<E> clazz, String propertyName) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public Map<PK, T> getInherentEntities() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Map<Class<?>, Map<Serializable, Object>> loadProperties(Object entityPo, Class<?> entityClass, String propertyList,
			Map<Class<?>, Map<Serializable, Object>> propertyValueCache) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean isPropertyNonNull(Class<?> entityClass, String propertyName) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public <E> Map<Class<?>, Map<Serializable, Object>> loadProperties(Collection<E> list, Class<E> clazz, String propertyList,
			Map<Class<?>, Map<Serializable, Object>> propertyValueCache) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Map<String, Class<?>> getForeignKeyMap() {
		// TODO Auto-generated method stub
		return null;
	}
}